/**
 * File: BamLoadController.java
 * Created by: mhaimel
 * Created on: Jun 17, 2011
 * CVS:  $Id: BamLoadController.java 1.0 Jun 17, 2011 4:13:10 PM mhaimel Exp $
 */
package uk.ac.ebi.curtain.controller.loader;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ConcurrentMap;

import uk.ac.ebi.curtain.controller.ParallelSingleSubmitController;
import uk.ac.ebi.curtain.controller.SimpleReport;
import uk.ac.ebi.curtain.management.IControllerReport;
import uk.ac.ebi.curtain.processor.load.impl.BamFullmatchProcessor;
import uk.ac.ebi.curtain.storage.sequence.fast.FastSequenceBoxWriter;
import uk.ac.ebi.curtain.utils.CurtainUncheckedException;
import uk.ac.ebi.curtain.utils.concurrent.UtilsCollect;
import uk.ac.ebi.curtain.utils.data.DataEntry;
import uk.ac.ebi.curtain.utils.data.FileType;
import uk.ac.ebi.curtain.utils.data.MetaData;
import uk.ac.ebi.curtain.utils.data.ReadType;
import uk.ac.ebi.curtain.utils.data.impl.GenericDataHolder;
import uk.ac.ebi.curtain.utils.file.FileInfo;

/**
 * @author mhaimel
 *
 */
public class BamLoadController extends ParallelSingleSubmitController<DataEntry<File>, String, BamFullmatchProcessor> {

	private static final Object _LOCK_OBJ = new Object();
	private final ConcurrentMap<String, FastSequenceBoxWriter> sbMap = UtilsCollect.newConcurrentMap();

	/**
	 * {@inheritDoc}
	 */
	@Override
	protected void singleSubmit(List<DataEntry<File>> inputList) {
		List<FileInfo> files = getContext().getArguments().getFiles(FileType.bam);
		for(FileInfo fi : files){
			Integer cat = getContext().getArguments().getCategory(fi);
			BamFullmatchProcessor loader = getContext().getInjector().getInstance(BamFullmatchProcessor.class);
			loader.setMappingQualityCutoff(getContext().getArguments().getMappingQualityCutoff().get());
			loader.setSequenceBoxWriter(getSequenceBoxWriter(fi.getReadType(), cat, true));
			loader.setSequenceBoxArcWriter(getSequenceBoxWriter(fi.getReadType(), cat,false));
			loader.setInput(new GenericDataHolder<File>(new MetaData(cat, fi.getFileType(), fi.getReadType()), fi.getFile()));
			submit(loader);
		}
	}
	
	private FastSequenceBoxWriter getSequenceBoxWriter(ReadType readType, Integer category, boolean mapped) {
		if(!readType.isIn(ReadType.getPaired())){
			return null;
		}
		synchronized (_LOCK_OBJ) {
			String key = category+"-"+readType+"-"+mapped;
			FastSequenceBoxWriter writer = sbMap.get(key);
			if(null == writer){
				writer = new FastSequenceBoxWriter(getContext().currentFiles().getSequenceBoxMapping(readType, category, mapped), false);
				try {
					writer.open();
				} catch (IOException e) {
					throw new CurtainUncheckedException(e);
				}
				sbMap.put(key, writer);
			}
			return writer;
		}
	}

	@Override
	protected void doShutdown() {
		try {
			for(FastSequenceBoxWriter w : sbMap.values()){
				getLog().debug("Close writer " + w.getFile());
				w.close(); // Close all first before sorting
			}
			
			for(FastSequenceBoxWriter w : sbMap.values()){
				getLog().debug("Sort and rewrite " + w.getFile());
				w.sort();
			}
		} catch (IOException e1) {
			throw new CurtainUncheckedException(e1);
		}
		getLog().debug("Build Arc index ...");
		getContext().getGraph().getGraph().buildArcsIndex();
		getContext().getGraph().getGraph().reindexArcs();
		super.doShutdown();
	}

	@Override
	protected IControllerReport getReturnCall() {
		return new SimpleReport("Finished loading Bam files!");
	}

}
